////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
#include "irrlicht.h"

#include "Sprite.h"
//#include "Lib2D/Rect.h"
//#include "Lib2D/SpriteInstance.h"

#include "Lib2D/UIInfo.h"
#include "Io/FileSystem/BinaryFile.h"
//#include "Application.h"
#include "CImage.h"
#include "ISceneManager.h"
#include "ICameraSceneNode.h"

#include "CNullDriver.h"
#include "../CGlobals.h"


extern CGlobals* g;

using namespace irr;
using namespace irr::io;
using namespace irr::video;
using namespace core;

////////////////////////////////////////////////////////////////////////////////////////////////////

#define ARRAY_SIZE_ALIGNED4(len,type)		((((len) * sizeof(type)) + 3) & (~3))

// allocate mem in internal buffer
#define SPR_MEM_ALLOC(ptr, type, size)		ptr = (type*)m_pInternalBufferPointer;	\
											m_pInternalBufferPointer += ARRAY_SIZE_ALIGNED4(size, type);


////////////////////////////////////////////////////////////////////////////////////////////////////
// 
#	define SWAP_SHORT(val)				;
#	define SWAP_SHORT_ARRAY(ptr, len)	;
////////////////////////////////////////////////////////////////////////////////////////////////////

irr::core::rect<s32>* CSprite::s_clipRect = NULL;

////////////////////////////////////////////////////////////////////////////////////////////////////

void CSprite::SetClip(int x, int y, int w, int h)
{
	s_clipRect = new irr::core::rect<s32>();
	s_clipRect->UpperLeftCorner.X = x;
	s_clipRect->UpperLeftCorner.Y = y;
	s_clipRect->LowerRightCorner.X = x + w;
	s_clipRect->LowerRightCorner.Y = y + h;
}

void CSprite::ResetClip()
{
	SAFE_DEL(s_clipRect);
}

////////////////////////////////////////////////////////////////////////////////////////////////////

CSprite::CSprite()
{
	// Buffers...
	m_pInternalBuffer			=	NULL;
	m_pInternalBufferPointer	=	NULL;

	// Modules...
	m_nModules					=	0;
	m_pModules_Type				=	NULL;
	m_pModules_Width			=	NULL;
	m_pModules_Height			=	NULL;
	m_pModules_X				=	NULL;
	m_pModules_Y				=	NULL;

	//// UV...
	//m_pModules_U1				=	NULL;
	//m_pModules_V1				=	NULL;
	//m_pModules_U2				=	NULL;
	//m_pModules_V2				=	NULL;

	// FModules...
	m_nFModules					=	0;
	m_pFModules_Module			=	NULL;
	m_pFModules_Flags			=	NULL;
	m_pFModules_OffsetX			=	NULL;
	m_pFModules_OffsetY			=	NULL;

	// Frames...
	m_nFrames					=	0;
	m_pFrames_NoFModules		=	NULL;
	m_pFrames_FM_Start			=	NULL;
	m_pFrames_RC				=	NULL;
	
	// AFrames...
	m_nAFrames					=	0;
	m_pAFrames_Frame			=	NULL;
	m_pAFrames_Time				=	NULL;
	m_pAFrames_OffsetX			=	NULL;
	m_pAFrames_OffsetY			=	NULL;
	m_pAFrames_Flags			=	NULL;

	// Anims...
	m_nAnims					=	0;
	m_pAnims_NoAFrames			=	NULL;
	m_pAnims_AF_Start			=	NULL;

	//Texture...
	//m_pTexture					=	NULL;

	m_pMaterial = new video::SMaterial();
	m_pMaterial->setFlag(EMF_LIGHTING, false);
	//m_pMaterial->setFlag(EMF_2D_USE_TEXTURE_ALPHA, true);
	//m_pMaterial->setMaterialType(EMT_TRANSPARENT_ALPHA_CHANNEL);
	m_pMaterial->setFlag(irr::video::EMF_ZBUFFER, false);
	m_pMaterial->setFlag(irr::video::EMF_ZWRITE_ENABLE, false);

#ifdef _IRR_USE_RIGHT_HAND_CONVENTION_
	m_aIndices[0] = 0;
	m_aIndices[1] = 1;
	m_aIndices[2] = 2;
	m_aIndices[3] = 0;
	m_aIndices[4] = 2;
	m_aIndices[5] = 3;
#else
	m_aIndices[0] = 0;
	m_aIndices[1] = 2;
	m_aIndices[2] = 1;
	m_aIndices[3] = 0;
	m_aIndices[4] = 3;
	m_aIndices[5] = 2;
#endif

	m_aVertices[0].Color = video::SColor(0xffffffff);
	m_aVertices[1].Color = video::SColor(0xffffffff);
	m_aVertices[2].Color = video::SColor(0xffffffff);
	m_aVertices[3].Color = video::SColor(0xffffffff);

	m_fAngle = 0.0f;
	m_fModuleDepth = 0.0f;

	m_nCrtPalette				=	0;

	SetScale(1.0f);

	SetAngle(quaternion());

	SetColor(0xFFFFFFFF);

	//m_filterType = irr::video::ETFT_LINEAR;
	m_imageEnlargeRate = 1.0f;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

CSprite::~CSprite()
{
	SAFE_DEL_ARRAY(m_pInternalBuffer);

	SAFE_DEL(m_pMaterial);
	
	g->device->getVideoDriver()->removeTexture(m_pTexture);
	m_pTexture = NULL;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

int CSprite::LoadSprite(CBinaryFile* pFile)
{
	int ret;

	ret = LoadSpriteData(pFile);

	if( ret < 0 )
		return ret;

	ret = LoadSpriteImage(pFile);

	return ret;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

int CSprite::LoadSpriteData(CBinaryFile* pFile)
{
	int size;

	// version
	u16 nVersion = pFile->ReadU16();
	ASSERT( nVersion == BSPRITE_VERSION );

	m_nFlags		=	pFile->ReadU16();

	// header
	m_nModules		=	pFile->ReadU16();
	m_nFModules		=	pFile->ReadU16();
	m_nFrames		=	pFile->ReadU16();
	m_nAFrames		=	pFile->ReadU16();
	m_nAnims		=	pFile->ReadU16();

	// compute size for internal buffer
	size =	ARRAY_SIZE_ALIGNED4(m_nModules,  u8) +
			ARRAY_SIZE_ALIGNED4(m_nModules,  s16) + 
			ARRAY_SIZE_ALIGNED4(m_nModules,  s16) +
			ARRAY_SIZE_ALIGNED4(m_nModules,  u16) + 
			ARRAY_SIZE_ALIGNED4(m_nModules,  u16) +

			ARRAY_SIZE_ALIGNED4(m_nFModules, u16) +
			ARRAY_SIZE_ALIGNED4(m_nFModules,  u8) +
			ARRAY_SIZE_ALIGNED4(m_nFModules, s16) +
			ARRAY_SIZE_ALIGNED4(m_nFModules, s16) +

			ARRAY_SIZE_ALIGNED4(m_nFrames,   u8) +
			ARRAY_SIZE_ALIGNED4(m_nFrames,   s16) +
			ARRAY_SIZE_ALIGNED4(m_nFrames, SRect) +

			ARRAY_SIZE_ALIGNED4(m_nAFrames,  u16) +
			ARRAY_SIZE_ALIGNED4(m_nAFrames,   u8) +
			ARRAY_SIZE_ALIGNED4(m_nAFrames,   u8) +
			ARRAY_SIZE_ALIGNED4(m_nAFrames,  s16) +
			ARRAY_SIZE_ALIGNED4(m_nAFrames,  s16) +

			ARRAY_SIZE_ALIGNED4(m_nAnims,    u8) +
			ARRAY_SIZE_ALIGNED4(m_nAnims,    s16) ;

	// allocate internal buffer
	m_pInternalBuffer			=	NEW u8[size];
	m_pInternalBufferPointer	= m_pInternalBuffer;

	// allocate from internal buffer
	SPR_MEM_ALLOC(m_pModules_Type,			u8, m_nModules);
	SPR_MEM_ALLOC(m_pModules_X,				s16, m_nModules);
	SPR_MEM_ALLOC(m_pModules_Y,				s16, m_nModules);
	SPR_MEM_ALLOC(m_pModules_Width,			u16, m_nModules);
	SPR_MEM_ALLOC(m_pModules_Height,		u16, m_nModules);

	SPR_MEM_ALLOC(m_pFModules_Module,		u16, m_nFModules);
	SPR_MEM_ALLOC(m_pFModules_Flags,		u8, m_nFModules);
	SPR_MEM_ALLOC(m_pFModules_OffsetX,		s16, m_nFModules);
	SPR_MEM_ALLOC(m_pFModules_OffsetY,		s16, m_nFModules);

	SPR_MEM_ALLOC(m_pFrames_NoFModules,		u8,  m_nFrames);
	SPR_MEM_ALLOC(m_pFrames_FM_Start,		u16, m_nFrames);
	SPR_MEM_ALLOC(m_pFrames_RC,				SRect, m_nFrames);

	SPR_MEM_ALLOC(m_pAFrames_Frame,			u16, m_nAFrames);
	SPR_MEM_ALLOC(m_pAFrames_Time,			u8, m_nAFrames);
	SPR_MEM_ALLOC(m_pAFrames_Flags,			u8, m_nAFrames);
	SPR_MEM_ALLOC(m_pAFrames_OffsetX,		s16, m_nAFrames);
	SPR_MEM_ALLOC(m_pAFrames_OffsetY,		s16, m_nAFrames);

	SPR_MEM_ALLOC(m_pAnims_NoAFrames,		u8,  m_nAnims);
	SPR_MEM_ALLOC(m_pAnims_AF_Start,		u16, m_nAnims);

	ASSERT(m_pInternalBufferPointer - m_pInternalBuffer <= size);

	// load modules..

	//if(m_nFlags & BST_FLAG_MODULE_TYPE)
	//{
		pFile->Read(m_pModules_Type, m_nModules);
	//}

	pFile->Read(m_pModules_X, m_nModules * sizeof(s16)); //SWAP_SHORT_ARRAY(pTmpU, m_nModules);
	pFile->Read(m_pModules_Y, m_nModules * sizeof(s16)); //SWAP_SHORT_ARRAY(pTmpV, m_nModules);

	pFile->Read(m_pModules_Width,  m_nModules * sizeof(u16)); SWAP_SHORT_ARRAY(m_pModules_Width,  m_nModules);
	pFile->Read(m_pModules_Height, m_nModules * sizeof(u16)); SWAP_SHORT_ARRAY(m_pModules_Height, m_nModules);

	// load fmodules..
	pFile->Read(m_pFModules_Module,  m_nFModules * sizeof(u16)); SWAP_SHORT_ARRAY(m_pFModules_Module, m_nFModules);
	pFile->Read(m_pFModules_Flags,   m_nFModules * sizeof(u8));
	pFile->Read(m_pFModules_OffsetX, m_nFModules * sizeof(s16)); SWAP_SHORT_ARRAY(m_pFModules_OffsetX, m_nFModules);
	pFile->Read(m_pFModules_OffsetY, m_nFModules * sizeof(s16)); SWAP_SHORT_ARRAY(m_pFModules_OffsetY, m_nFModules);

	// load frames..
	pFile->Read(m_pFrames_NoFModules,  m_nFrames * sizeof(u8)); //SWAP_SHORT_ARRAY(m_pFrames_NoFModules, m_nFrames);
	pFile->Read(m_pFrames_FM_Start,    m_nFrames * sizeof(u16)); SWAP_SHORT_ARRAY(m_pFrames_FM_Start, m_nFrames);

	// load aframes..
	pFile->Read(m_pAFrames_Frame,   m_nAFrames * sizeof(u16)); SWAP_SHORT_ARRAY(m_pAFrames_Frame, m_nAFrames);
	pFile->Read(m_pAFrames_Time,    m_nAFrames * sizeof(u8));
	pFile->Read(m_pAFrames_Flags,   m_nAFrames * sizeof(u8));
	pFile->Read(m_pAFrames_OffsetX, m_nAFrames * sizeof(s16)); SWAP_SHORT_ARRAY(m_pAFrames_OffsetX, m_nAFrames);
	pFile->Read(m_pAFrames_OffsetY, m_nAFrames * sizeof(s16)); SWAP_SHORT_ARRAY(m_pAFrames_OffsetY, m_nAFrames);

	// load anims..
	pFile->Read(m_pAnims_NoAFrames, m_nAnims * sizeof(u8)); //SWAP_SHORT_ARRAY(m_pAnims_NoAFrames, m_nAnims);
	pFile->Read(m_pAnims_AF_Start,  m_nAnims * sizeof(u16)); SWAP_SHORT_ARRAY(m_pAnims_AF_Start, m_nAnims);

	if (m_nFrames)
	{
		// compute frames rect
		for ( int i = 0, off = 0; i < m_nFrames; i++ )
		{
			int minX = (1 << 30);
			int minY = (1 << 30);
			int maxX = -(1 << 30);
			int maxY = -(1 << 30);

			for ( int j = 0; j < GetFModules( i ); j++ )
			{
				irr::core::rect<short> rc;

				GetFModuleRect( rc, i, j, 0, 0, 0 );

				minX = MIN( minX, rc.UpperLeftCorner.X );
				minY = MIN( minY, rc.UpperLeftCorner.Y );
				maxX = MAX( maxX, rc.LowerRightCorner.X );
				maxY = MAX( maxY, rc.LowerRightCorner.Y );
			}

			m_pFrames_RC[i].X = (s16)minX;
			m_pFrames_RC[i].Y = (s16)minY;
			m_pFrames_RC[i].W = (s16)maxX - minX;
			m_pFrames_RC[i].H = (s16)maxY - minY;
		}	
	}

	return 0;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
#define READ_IMAGE_FROM_PACKAGE
int CSprite::LoadSpriteImage(CBinaryFile* pFile)
{
#if defined(READ_IMAGE_FROM_PACKAGE)
	const irr::c8 *pBSpriteName = pFile->getFileName().c_str();
	irr::c8 tmp[256];
	irr::c8 ImageNameString[256];
	const char * pos = strstr(pBSpriteName,".bsprite");
	strcpy( tmp, pBSpriteName );
	tmp[pos-pBSpriteName] = '\0';
	strcpy(ImageNameString,tmp);

	irr::c8 ImageFileName[256];
	strcpy(ImageFileName, ImageNameString );

	strcat(ImageNameString,".tga");

	irr::IrrlichtDevice *pDevice = g->device;
	irr::io::IFileSystem *pFileSystem = pDevice->getFileSystem();
	ASSERT( pFileSystem->existFile( ImageNameString ) );
	//LOG("SpriteLoading","texture=%s",ImageNameString);

	irr::c8 ImageEnlargeName[256];
	m_imageEnlargeRate = GetEnlargeRate(ImageFileName,ImageEnlargeName);
	//LOG("SpriteLoading","m_imageEnlargeRate=%f,fileName=%s",m_imageEnlargeRate,ImageEnlargeName);
	//OutputInfoFor_iPhone("m_imageEnlargeRate=%f,fileName=%s",m_imageEnlargeRate,ImageEnlargeName);

	irr::video::CNullDriver* nullDriver = (irr::video::CNullDriver*)g->driver;
	//nullDriver->setTextureFullPathMode(false);
	m_pTexture = g->device->getVideoDriver()->getTexture(ImageEnlargeName);	
	//nullDriver->setTextureFullPathMode(true);
	//m_pTexture->setMinFilter(m_filterType);
	//m_pTexture->setMagFilter(m_filterType);

	//if( stricmp( ImageNameString, "interface.tga") == 0)
	//{
	//	m_pTexture->setMinFilter(irr::video::ETFT_NEAREST);
	//	m_pTexture->setMagFilter(irr::video::ETFT_NEAREST);
	//}
	//else
	//{
	//	m_pTexture->setMinFilter(m_filterType);
	//	m_pTexture->setMagFilter(m_filterType);
	//}
#else
	// reading image info
	short pixelFormat = pFile->ReadU16();
	pFile->ReadU16();
	int imgW = pFile->ReadU16();
	int imgH = pFile->ReadU16();

	// reading raw encoded data
	switch (pixelFormat)
	{
		case PIXEL_FORMAT_8888:
		{
			char* imgData = new char[imgW * imgH * 4];

			//pFile->Read(imgData, imgSize);
			int wIdx = 0;
			for (int i = imgW * imgH - 1; i >= 0; i--)
			{
				int c = pFile->ReadU32();

				imgData[wIdx++] = (c >> 24) & 0xFF;
				imgData[wIdx++] = (c >> 16) & 0xFF;
				imgData[wIdx++] = (c >> 8 ) & 0xFF;
				imgData[wIdx++] = (c      ) & 0xFF;
			}

			IImage* img = new CImage(ECF_A8R8G8B8, dimension2d<s32>(imgW, imgH), imgData);
			m_pTexture = Application::instance()->GetDevice()->getVideoDriver()->addTexture(pFile->getFileName(), img);
			delete img;
			break;
		}

		case PIXEL_FORMAT_0888:
		{
			char* imgData = new char[imgW * imgH * 3];

			//pFile->Read(imgData, imgSize);
			int wIdx = 0;
			for (int i = imgW * imgH - 1; i >= 0; i--)
			{
				char r = pFile->ReadU8();
				char g = pFile->ReadU8();
				char b = pFile->ReadU8();

				imgData[wIdx++] = b;
				imgData[wIdx++] = g;
				imgData[wIdx++] = r;
			}

			IImage* img = new CImage(ECF_R8G8B8, dimension2d<s32>(imgW, imgH), imgData);
			m_pTexture = Application::instance()->GetDevice()->getVideoDriver()->addTexture(pFile->getFileName(), img);
			delete img;
			break;
		}
	}
#endif

	return 0;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

//bool CSprite::IsImagePixelTransparent(int x, int y)
//{
//	u8 *data = m_pTexture->GetTexBuffer();
//	int fmt = m_pTexture->GetTexFmt();
//
////	y = pTex->SizeY()-y-1; //image is flipped
//
//#if defined(OS_WIN32)
////	return (data[y * m_pTexture->SizeX() + x] == 0);
//	if (m_nFlags & BST_TYPE_INDEXED)
//	{
//		return (data[y * m_pTexture->SizeX() + x] == 0);
//	}
//	if (m_nFlags & BST_TYPE_RGB16)
//	{
//		u16 *p = (u16*)data;
//		return (p[y * m_pTexture->SizeX() + x] == 0x0f0f);
//	}
//	if (m_nFlags & BST_TYPE_RGB32)
//	{
//		u32 *p = (u32*)data;
//		return (p[y * m_pTexture->SizeX() + x] == 0xffff00ff);
//	}
//#else
//	int tileX = 8;
//	int tileY = 4;
//
//	if (m_nFlags & BST_TYPE_RGB16)
//		tileX = 4;
//
//	int sqX = x / tileX;
//	int sqY = y / tileY;
//
//	int tlX  = x % tileX;
//	int tlY = y % tileY;
//
//	int nrX = m_pTexture->SizeX()/tileX;
//	int nrY = m_pTexture->SizeY()/tileY;
//
//	data += (sqY * nrX + sqX)*32;
//
//	if (m_nFlags & BST_TYPE_INDEXED)
//	{
//		return (data[tlY * tileX + tlX]==0);
//	}
//	if (m_nFlags & BST_TYPE_RGB16)
//	{
//		u16 *p = (u16*)data;
//		return (p[tlY * tileX + tlX]==0x0f0f);
//	}
//	if (m_nFlags & BST_TYPE_RGB32)
//	{
//		u32 *p = (u32*)data;
//		return (p[tlY * tileX + tlX]==0xffff00ff);
//	}
//#endif
//	return TRUE ;
//}
//
//////////////////////////////////////////////////////////////////////////////////////////////////////
//
//bool CSprite::IsModulePixelTransparent(int module, int moduleX, int moduleY, int pixelX, int pixelY, int flags)
//{
//	int mw = m_pModules_Width[module];
//	int mh = m_pModules_Height[module];
//	int mx = (int)(m_pModules_U1[module] * m_pTexture->SizeX());
//	int my = (int)(m_pModules_V1[module] * m_pTexture->SizeY());
//
//	if ((pixelX<moduleX) || (pixelY<moduleY) || (pixelX >= moduleX + mw) || (pixelY >= moduleY + mh))
//		return true;
//
//	int px, py;
//
//	if (flags & FLAG_FLIP_X)
//		px = mx + mw - (pixelX-moduleX) - 1;
//	else
//		px = mx + pixelX - moduleX;
//
//	if (flags & FLAG_FLIP_Y)
//		py = my + mh - (pixelY-moduleY) - 1;
//	else
//		py = my + pixelY - moduleY;
//
//	return IsImagePixelTransparent(px, py);
//}
//
//////////////////////////////////////////////////////////////////////////////////////////////////////
//
//bool CSprite::IsFModulePixelTransparent(int frame, int fmodule, int fmoduleX, int fmoduleY, int pixelX, int pixelY, int flags)
//{
//	ASSERT( 0 <= frame && frame < m_nFrames );
//
//	int off      = m_pFrames_FM_Start[ frame ] + fmodule;
//	int fm_flags = m_pFModules_Flags[ off ];
//	int index    = m_pFModules_Module[ off ];
//
//	if ( flags & FLAG_FLIP_X )	
//		fmoduleX -= m_pFModules_OffsetX[ off ];
//	else						
//		fmoduleX += m_pFModules_OffsetX[ off ];
//
//	if ( flags & FLAG_FLIP_Y )	
//		fmoduleY -= m_pFModules_OffsetY[ off ];
//	else						
//		fmoduleY += m_pFModules_OffsetY[ off ];
//
//	if ( ( fm_flags & FLAG_HYPER_FM ) != 0 )
//	{
//		return IsFramePixelTransparent( index, fmoduleX, fmoduleY, pixelX,pixelY, flags ^ fm_flags);
//	}
//	else
//	{
//		if ( flags & FLAG_FLIP_X )	fmoduleX -= GetModuleWidth(index);
//		if ( flags & FLAG_FLIP_Y )	fmoduleY -= GetModuleHeight(index);
//
//		return IsModulePixelTransparent( index, fmoduleX, fmoduleY, pixelX, pixelY, flags ^ fm_flags);
//	}
//}
//
//////////////////////////////////////////////////////////////////////////////////////////////////////
//
//bool CSprite::IsFramePixelTransparent(int frame, int frameX, int frameY, int pixelX, int pixelY, int flags)
//{
//	ASSERT( 0 <= frame && frame < m_nFrames );
//
//	CRect r;
//
//	GetFrameRect(&r, frame, frameX, frameY, flags, 0, 0);
//	if ((pixelX < r.GetX1()) || (pixelY < r.GetY1()) || (pixelX>r.GetX2()) || (pixelY > r.GetY2()))
//		return true;
//
//	int nFModules = m_pFrames_NoFModules[ frame ];	// number of frame modules for this frame
//
//	for ( int fmodule = 0; fmodule < nFModules; fmodule++ )
//	{
//		if (!IsFModulePixelTransparent( frame, fmodule, frameX, frameY, pixelX, pixelY, flags))
//			return false;
//	}
//
//	return true;
//}
//
//bool CSprite::IsFramePixelTransparentR(int frame, int frameX, int frameY, int pixelX, int pixelY, int flags, int radius)
//{
//	if (!IsFramePixelTransparent(frame, frameX, frameY, pixelX, pixelY, flags))
//		return false;
//
//	for (int i=pixelX-radius;i<=pixelX+radius;i++)
//	{
//		if (!IsFramePixelTransparent(frame, frameX, frameY, i, pixelY-radius, flags))
//			return false;
//		if (!IsFramePixelTransparent(frame, frameX, frameY, i, pixelY+radius, flags))
//			return false;
//	}
//
//	for (int i=pixelY-radius+1;i<pixelY+radius;i++)
//	{
//		if (!IsFramePixelTransparent(frame, frameX, frameY, pixelX-radius, i, flags))
//			return false;
//		if (!IsFramePixelTransparent(frame, frameX, frameY, pixelX+radius, i, flags))
//			return false;
//	}
//
//	return true;
//}


////////////////////////////////////////////////////////////////////////////////////////////////////

void CSprite::PaintAFrame( int anim, int aframe, int posX, int posY, u32 flags, u8 alpha )
{
	ASSERT( 0 <= anim && anim < m_nAnims );

	int off   = m_pAnims_AF_Start[ anim ] + aframe;
	int frame = m_pAFrames_Frame[ off ];

	if ((flags & FLAG_OFFSET_AF) == 0)
	{
		if (flags & FLAG_FLIP_X)	posX -= (int)( m_pAFrames_OffsetX[ off ] * m_fScale);
		else						posX += (int)( m_pAFrames_OffsetX[ off ] * m_fScale);
		if (flags & FLAG_FLIP_Y)	posY -= (int)( m_pAFrames_OffsetY[ off ] * m_fScale);
		else						posY += (int)( m_pAFrames_OffsetY[ off ] * m_fScale);
	}

	PaintFrame( frame, posX, posY, flags ^ m_pAFrames_Flags[ off ], alpha );
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void CSprite::PaintFrame( int frame, int posX, int posY, u32 flags, u8 alpha, bool isUseAlphaChannelOfTexture )
{
	ASSERT( 0 <= frame && frame < m_nFrames );

	m_rotateX = posX;
	m_rotateY = posY;

	int nFModules = m_pFrames_NoFModules[ frame ];	// number of frame modules for this frame

	for ( int fmodule = 0; fmodule < nFModules; fmodule++ )
	{
		PaintFModule( frame, fmodule, posX, posY, flags, alpha, isUseAlphaChannelOfTexture );
	}
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void CSprite::PaintFModule( int frame, int fmodule, int posX, int posY, u32 flags, u8 alpha, bool isUseAlphaChannelOfTexture )
{
	ASSERT( 0 <= frame && frame < m_nFrames );

	int off      = m_pFrames_FM_Start[ frame ] + fmodule;
	int fm_flags = m_pFModules_Flags[ off ];
	int index    = m_pFModules_Module[ off ];

	if( s_clipRect )
	{
		if ( flags & FLAG_FLIP_X )	posX -= (int)(GetFModuleOffsetX(off) * m_fScale);
		else						posX += (int)(GetFModuleOffsetX(off) * m_fScale);
		if ( flags & FLAG_FLIP_Y )	posY -= (int)(GetFModuleOffsetY(off) * m_fScale);
		else						posY += (int)(GetFModuleOffsetY(off) * m_fScale);


		if ( flags & FLAG_FLIP_X )	posX -= (int)(GetModuleWidth(index) * m_fScale);
		if ( flags & FLAG_FLIP_Y )	posY -= (int)(GetModuleHeight(index) * m_fScale);
	}
	else
	{
		if ( flags & FLAG_FLIP_X )	posX -= (int)(GetFModuleOffsetX(off) );
		else						posX += (int)(GetFModuleOffsetX(off) );
		if ( flags & FLAG_FLIP_Y )	posY -= (int)(GetFModuleOffsetY(off) );
		else						posY += (int)(GetFModuleOffsetY(off) );

		if ( flags & FLAG_FLIP_X )	posX -= (int)(GetModuleWidth(index) );
		if ( flags & FLAG_FLIP_Y )	posY -= (int)(GetModuleHeight(index) );
	}

	

	PaintModule( index, posX, posY, flags ^ fm_flags, alpha, isUseAlphaChannelOfTexture);
}

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

void CSprite::PaintModule( int module, int posX, int posY, u32 flags, u8 alpha, bool isUseAlphaChannelOfTexture )
{
	ASSERT( 0 <= module && module < m_nModules );
	ASSERT( m_pTexture );

	//Draw stuff here
	if (IsModuleImage(module))
	{
		int srcPosX = m_pModules_X[module];
		int srcPosY = m_pModules_Y[module];
		int sizeX = m_pModules_Width[module];
		int sizeY = m_pModules_Height[module];

		if (sizeX <= 0 || sizeY <= 0)
			return;

		video::IVideoDriver* videoDriver = g->device->getVideoDriver();
		//m_pMaterial->setFlag(irr::video::EMF_2D_USE_VERTEX_ALPHA, isUseAlphaChannelOfTexture);
		//videoDriver->set2DUseVertexAlpha(isUseAlphaChannelOfTexture);

		//if (m_fAngle != 0.0f)
		if(s_clipRect == NULL)
		{
			//for (s32 i=0; i<4; ++i)
			//	m_aVertices[i].Normal = view;			
			float xRate = 1.0f;//UIInfo::instance()->GetScaleRateX();
			float yRate = 1.0f;//UIInfo::instance()->GetScaleRateY();

			SColor color (alpha , 0xFF, 0xFF, 0xFF);

			m_aVertices[0].Pos.X = (posX + sizeX)*xRate ;
			m_aVertices[0].Pos.Y = (posY + sizeY)*yRate ;
			m_aVertices[0].Pos.Z = 0.0f;
			m_aVertices[0].Color = color;

			m_aVertices[1].Pos.X = (posX + sizeX)*xRate;
			m_aVertices[1].Pos.Y = posY*yRate;
			m_aVertices[1].Pos.Z = 0.0f;
			m_aVertices[1].Color = color;

			m_aVertices[2].Pos.X = posX*xRate;
			m_aVertices[2].Pos.Y = posY*yRate;
			m_aVertices[2].Pos.Z = 0.0f;
			m_aVertices[2].Color = color;

			m_aVertices[3].Pos.X = posX*xRate;
			m_aVertices[3].Pos.Y = (posY + sizeY)*yRate;
			m_aVertices[3].Pos.Z = 0.0f;
			m_aVertices[3].Color = color;

			if( (m_fAngle != 0.0f) || (m_fScale != 1.0f) )
			{
				if( (m_fAngle != 0.0f) && (m_fScale == 1.0f) )
				{
					matrix4 m, m1, m2, m3;

					m1.setTranslation(vector3df(m_rotateX*xRate, m_rotateY*yRate, 0));
					m2.setRotationDegrees(vector3df(0.0f, 0.0f, m_fAngle));
					m3.setTranslation(vector3df(-(m_rotateX*xRate), -(m_rotateY*yRate), 0));

					m = m1 * m2 * m3;

					m.transformVect(m_aVertices[0].Pos);
					m.transformVect(m_aVertices[1].Pos);
					m.transformVect(m_aVertices[2].Pos);
					m.transformVect(m_aVertices[3].Pos);
				}
				else if( (m_fAngle == 0.0f) && (m_fScale != 1.0f) )
				{
					matrix4 m, m1, m2, m3;

					m1.setTranslation(vector3df(m_rotateX*xRate, m_rotateY*yRate, 0));
					m2.setScale(vector3df(m_fScale, m_fScale, 1.0f) );
					m3.setTranslation(vector3df(-(m_rotateX*xRate), -(m_rotateY*yRate), 0));

					m = m1 * m2 * m3;

					m.transformVect(m_aVertices[0].Pos);
					m.transformVect(m_aVertices[1].Pos);
					m.transformVect(m_aVertices[2].Pos);
					m.transformVect(m_aVertices[3].Pos);
				}
				else
				{
					matrix4 m, m1, m2, m3,m4;

					m1.setTranslation(vector3df(m_rotateX*xRate, m_rotateY*yRate, 0));
					m2.setRotationDegrees(vector3df(0.0f, 0.0f, m_fAngle));
					m3.setTranslation(vector3df(-(m_rotateX*xRate), -(m_rotateY*yRate), 0));
					m4.setScale(vector3df(m_fScale, m_fScale, 1.0f) );

					m = m1 *m4 * m2 * m3;

					m.transformVect(m_aVertices[0].Pos);
					m.transformVect(m_aVertices[1].Pos);
					m.transformVect(m_aVertices[2].Pos);
					m.transformVect(m_aVertices[3].Pos);
				}
			}

			const dimension2d<u32> size = m_pTexture->getSize();
			const f32 invW = 1.f / static_cast<f32>(size.Width);
			const f32 invH = 1.f / static_cast<f32>(size.Height);

//	#if defined(TARGET_IPHONE_SIMULATOR) || defined(TARGET_OS_IPHONE)		
//			// sprite textures are not compressed (pvr),
//			// therefore textures are not y-flipped as expected (for iphone),
//			// so we do it manually.
//			m_aVertices[0].TCoords.set((srcPosX + sizeX)*invW, 1.f - (srcPosY + sizeY)*invH);
//			m_aVertices[1].TCoords.set((srcPosX + sizeX)*invW, 1.f - srcPosY*invH);
//			m_aVertices[2].TCoords.set(srcPosX*invW, 1.f - srcPosY*invH);
//			m_aVertices[3].TCoords.set(srcPosX*invW, 1.f - (srcPosY + sizeY)*invH);
//	#else
			m_aVertices[0].TCoords.set((srcPosX + sizeX)*m_imageEnlargeRate*invW, (srcPosY + sizeY)*m_imageEnlargeRate*invH);
			m_aVertices[1].TCoords.set((srcPosX + sizeX)*m_imageEnlargeRate*invW, srcPosY*m_imageEnlargeRate*invH);
			m_aVertices[2].TCoords.set(srcPosX*m_imageEnlargeRate*invW, srcPosY*m_imageEnlargeRate*invH);
			m_aVertices[3].TCoords.set(srcPosX*m_imageEnlargeRate*invW, (srcPosY + sizeY)*m_imageEnlargeRate*invH);
//	#endif

			if (flags & FLAG_FLIP_X)
			{
				std::swap(m_aVertices[0].TCoords, m_aVertices[3].TCoords);
				std::swap(m_aVertices[1].TCoords, m_aVertices[2].TCoords);
			}
			if (flags & FLAG_FLIP_Y)
			{
				std::swap(m_aVertices[0].TCoords, m_aVertices[1].TCoords);
				std::swap(m_aVertices[2].TCoords, m_aVertices[3].TCoords);
			}

			m_pMaterial->setTexture(0, m_pTexture);
			//videoDriver->set2DMaterial(*m_pMaterial);
			//videoDriver->set2DTexture(m_pTexture, isUseAlphaChannelOfTexture);

			//videoDriver->drawVertexPrimitiveList(m_aVertices, m_aIndices, 0, 4, 2, EVT_STANDARD, scene::EPT_TRIANGLES, EIT_16BIT);

			//irr::video::SMaterial mat;
			//videoDriver->set2DMaterial(mat);
		}
		else
		{
			SColor color (alpha , 0xFF, 0xFF, 0xFF);

			const SColor colorsArray[4] = { color, color, color, color };
			
			core::rect<s32> destRect( posX, posY, posX + sizeX * m_fScale, posY + sizeY * m_fScale);


			rect<s32> sourceRect(	flags & FLAG_FLIP_X ? srcPosX + sizeX : srcPosX,
									flags & FLAG_FLIP_Y ? srcPosY + sizeY : srcPosY,
									flags & FLAG_FLIP_X ? srcPosX : srcPosX + sizeX,
									flags & FLAG_FLIP_Y ? srcPosY : srcPosY + sizeY);
			
			sourceRect.UpperLeftCorner = sourceRect.UpperLeftCorner * m_imageEnlargeRate;
			sourceRect.LowerRightCorner = sourceRect.LowerRightCorner * m_imageEnlargeRate;

			float xRate = 1.0f;//UIInfo::instance()->GetScaleRateX();
			destRect.UpperLeftCorner.X *= xRate;
			destRect.LowerRightCorner.X *= xRate;

			float yRate = 1.0f;// UIInfo::instance()->GetScaleRateY();
			destRect.UpperLeftCorner.Y *= yRate;
			destRect.LowerRightCorner.Y *= yRate;

			//m_pMaterial->setTexture(0, m_pTexture);
//			videoDriver->set2DMaterial(*m_pMaterial);
//			videoDriver->set2DTexture(m_pTexture, isUseAlphaChannelOfTexture);

			//videoDriver->draw2DImage(m_pTexture, destRect, sourceRect, s_clipRect, colorsArray, isUseAlphaChannelOfTexture);

//			videoDriver->draw2DRectangle(destRect, sourceRect, colorsArray, s_clipRect);
		}
	}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

void CSprite::PaintAFrame( int anim, int aframe, const vector3df& pos, u32 flags, u8 alpha )
{
	ASSERT( 0 <= anim && anim < m_nAnims );

	int off   = m_pAnims_AF_Start[ anim ] + aframe;
	int frame = m_pAFrames_Frame[ off ];

	int offX = 0, offY = 0;

	if ((flags & FLAG_OFFSET_AF) == 0)
	{
		if (flags & FLAG_FLIP_X)	offX -= (int)m_pAFrames_OffsetX[ off ];
		else						offX += (int)m_pAFrames_OffsetX[ off ];
		if (flags & FLAG_FLIP_Y)	offY -= (int)m_pAFrames_OffsetY[ off ];
		else						offY += (int)m_pAFrames_OffsetY[ off ];
	}

	PaintFrame( frame, pos, flags ^ m_pAFrames_Flags[ off ], offX, offY, alpha );
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void CSprite::PaintFrame( int frame, const vector3df& pos, u32 flags, int offX, int offY, u8 alpha )
{
	ASSERT( 0 <= frame && frame < m_nFrames );

	int nFModules = m_pFrames_NoFModules[ frame ];	// number of frame modules for this frame

	for ( int fmodule = 0; fmodule < nFModules; fmodule++ )
	{
		PaintFModule( frame, fmodule, pos, flags, offX, offY, alpha );
		m_fModuleDepth += 0.005f;
	}
	m_fModuleDepth = 0.0f;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void CSprite::PaintFModule( int frame, int fmodule, const vector3df& pos, u32 flags, int offX, int offY, u8 alpha )
{
	ASSERT( 0 <= frame && frame < m_nFrames );

	int off      = m_pFrames_FM_Start[ frame ] + fmodule;
	int fm_flags = m_pFModules_Flags[ off ];
	int index    = m_pFModules_Module[ off ];

	//if ( fm_flags & FLAG_ROT_90 )
	//{
	//	if ( flags & FLAG_FLIP_X )	offY -= (int)GetFModuleOffsetX(off);
	//	else						offY += (int)GetFModuleOffsetX(off);

	//	if ( flags & FLAG_FLIP_Y )	offX -= (int)GetFModuleOffsetY(off);
	//	else						offX += (int)GetFModuleOffsetY(off);

	//	// switch X and Y flags
	//	flags = (flags & (~(FLAG_FLIP_X | FLAG_FLIP_Y))) |
	//			((flags & FLAG_FLIP_X) << 1) |
	//			((flags & FLAG_FLIP_Y) >> 1);
	//}
	//else
	{
		if ( flags & FLAG_FLIP_X )	offX -= (int)(GetFModuleOffsetX(off) + GetModuleWidth(index));
		else						offX += (int)GetFModuleOffsetX(off);

		if ( flags & FLAG_FLIP_Y )	offY -= (int)(GetFModuleOffsetY(off) + GetModuleHeight(index));
		else						offY += (int)GetFModuleOffsetY(off);
	}
	if ( fm_flags & FLAG_ROT_90 )
	{
		if ( flags & FLAG_FLIP_X )	offX -= (int)(GetModuleHeight(index) - GetModuleWidth(index));

		// switch X and Y flags
		flags = (flags & (~(FLAG_FLIP_X | FLAG_FLIP_Y))) |
				((flags & FLAG_FLIP_X) << 1) |
				((flags & FLAG_FLIP_Y) >> 1);
	}

	PaintModule( index, pos, flags ^ fm_flags, offX, offY, alpha);
}

//////////////////////////////////////////////////////////////////////////////////////////////////////

void CSprite::PaintModule( int module, const vector3df& pos, u32 flags, int offX, int offY, u8 alpha )
{
	ASSERT( 0 <= module && module < m_nModules );
	ASSERT( m_pTexture );

	//Draw stuff here
	if (IsModuleImage(module))
	{
		int srcPosX = m_pModules_X[module];
		int srcPosY = m_pModules_Y[module];
		int sizeX = m_pModules_Width[module];
		int sizeY = m_pModules_Height[module];

		if (sizeX <= 0 || sizeY <= 0)
			return;

		video::IVideoDriver* driver = g->device->getVideoDriver();
		scene::ICameraSceneNode* camera = g->device->getSceneManager()->getActiveCamera();

		if( camera == NULL )
		{
			return;
		}
		core::vector3df campos = camera->getAbsolutePosition();
		core::vector3df target = camera->getTarget();
		core::vector3df up = camera->getUpVector();
		core::vector3df view = target - campos;
		view.normalize();

		core::vector3df offset;

		core::vector3df horizontal = up.crossProduct(view);
		if ( horizontal.getLength() == 0 )
		{
			horizontal.set(up.Y,up.X,up.Z);
		}
		horizontal.normalize();
		offset += horizontal * offX * m_fScale;

		core::vector3df vertical = horizontal.crossProduct(view);
		vertical.normalize();
		offset += vertical * offY * m_fScale;

		view *= -1.0f;

		offset += m_fModuleDepth * view;

		for (s32 i=0; i<4; ++i)
			m_aVertices[i].Normal = view;

		if (flags & FLAG_ROT_90)
		{
			horizontal *= sizeY * m_fScale;
			vertical *= sizeX * m_fScale;

			m_aVertices[1].Pos = pos + horizontal + vertical + offset;
			m_aVertices[2].Pos = pos + horizontal + offset;
			m_aVertices[3].Pos = pos + offset;
			m_aVertices[0].Pos = pos + vertical + offset;
		}
		else
		{
			horizontal *= sizeX * m_fScale;
			vertical *= sizeY * m_fScale;

			m_aVertices[0].Pos = pos + horizontal + vertical + offset;
			m_aVertices[1].Pos = pos + horizontal + offset;
			m_aVertices[2].Pos = pos + offset;
			m_aVertices[3].Pos = pos + vertical + offset;
		}

		dimension2d<u32> size = m_pTexture->getSize();
		const f32 invW = 1.f / static_cast<f32>(size.Width);
		const f32 invH = 1.f / static_cast<f32>(size.Height);

#if defined(TARGET_IPHONE_SIMULATOR) || defined(TARGET_OS_IPHONE)		
		// sprite textures are not compressed (pvr),
		// therefore textures are not y-flipped as expected (for iphone),
		// so we do it manually.
		//m_aVertices[0].TCoords.set((srcPosX + sizeX)*invW, 1.f - (srcPosY + sizeY)*invH);
		//m_aVertices[1].TCoords.set((srcPosX + sizeX)*invW, 1.f - srcPosY*invH);
		//m_aVertices[2].TCoords.set(srcPosX*invW, 1.f - srcPosY*invH);
		//m_aVertices[3].TCoords.set(srcPosX*invW, 1.f - (srcPosY + sizeY)*invH);

		m_aVertices[0].TCoords.set((srcPosX + sizeX)*m_imageEnlargeRate*invW, (srcPosY + sizeY)*m_imageEnlargeRate*invH);
		m_aVertices[1].TCoords.set((srcPosX + sizeX)*m_imageEnlargeRate*invW, srcPosY*m_imageEnlargeRate*invH);
		m_aVertices[2].TCoords.set(srcPosX*m_imageEnlargeRate*invW, srcPosY*m_imageEnlargeRate*invH);
		m_aVertices[3].TCoords.set(srcPosX*m_imageEnlargeRate*invW, (srcPosY + sizeY)*m_imageEnlargeRate*invH);
#else
		m_aVertices[0].TCoords.set((srcPosX + sizeX)*m_imageEnlargeRate*invW, (srcPosY + sizeY)*m_imageEnlargeRate*invH);
		m_aVertices[1].TCoords.set((srcPosX + sizeX)*m_imageEnlargeRate*invW, srcPosY*m_imageEnlargeRate*invH);
		m_aVertices[2].TCoords.set(srcPosX*m_imageEnlargeRate*invW, srcPosY*m_imageEnlargeRate*invH);
		m_aVertices[3].TCoords.set(srcPosX*m_imageEnlargeRate*invW, (srcPosY + sizeY)*m_imageEnlargeRate*invH);
#endif

		if (flags & FLAG_FLIP_X)
		{
			std::swap(m_aVertices[0].TCoords, m_aVertices[3].TCoords);
			std::swap(m_aVertices[1].TCoords, m_aVertices[2].TCoords);
		}
		if (flags & FLAG_FLIP_Y)
		{
			std::swap(m_aVertices[0].TCoords, m_aVertices[1].TCoords);
			std::swap(m_aVertices[2].TCoords, m_aVertices[3].TCoords);
		}		

		// set identity matrix
		driver->setTransform(video::ETS_WORLD, matrix4());

		//_material->ZBuffer = 0;
		m_pMaterial->setTexture(0, m_pTexture);
		driver->setMaterial(*m_pMaterial);

		//driver->drawIndexedTriangleList(m_aVertices, 4, m_aIndices, 2);
		//driver->drawVertexPrimitiveList(m_aVertices, m_aIndices, 0, 4, 2, EVT_STANDARD, scene::EPT_TRIANGLES, EIT_16BIT);
	}
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void CSprite::GetAFrameRect( irr::core::rect<short>& rc, int anim, int aframe, int posX, int posY, u32 flags, int hx, int hy) const
{
	ASSERT( 0 <= anim && anim < m_nAnims );

	int off   = m_pAnims_AF_Start[ anim ] + aframe;
	int frame = m_pAFrames_Frame[ off ];


	#ifdef USE_INDEX_EX_AFRAMES

		frame |= ( ( m_pAFrames_Flags[ off ] & FLAG_INDEX_EX_MASK ) << INDEX_EX_SHIFT );

	#endif

	{
		if (flags & FLAG_FLIP_X)	hx += m_pAFrames_OffsetX[ off ];
		else						hx -= m_pAFrames_OffsetX[ off ];
		if (flags & FLAG_FLIP_Y)	hy += m_pAFrames_OffsetY[ off ];
		else						hy -= m_pAFrames_OffsetY[ off ];
	}

	GetFrameRect( rc, frame, posX, posY, flags ^ ( m_pAFrames_Flags[ off ] & 0x0F ), hx, hy );
}

//////////////////////////////////////////////////////////////////////////////////////////////////////

void CSprite::GetFrameRect( irr::core::rect<short>& rc, int frame, int posX, int posY, u32 flags, int hx, int hy ) const
{
	ASSERT( 0 <= frame && frame < m_nFrames );

	int fx = m_pFrames_RC[ frame ].X;
	int fy = m_pFrames_RC[ frame ].Y;
	int fw = m_pFrames_RC[ frame ].W;
	int fh = m_pFrames_RC[ frame ].H;

	if ( flags & FLAG_FLIP_X )	hx += fx + fw;
	else						hx -= fx;
	if ( flags & FLAG_FLIP_Y )	hy += fy + fh;
	else						hy -= fy;

	rc.UpperLeftCorner = position2d<short>(posX - hx, posY - hy);
	rc.LowerRightCorner = rc.UpperLeftCorner + position2d<short>(fw, fh);
	//rc->SetWH( posX - hx, posY - hy, fw, fh );
}

//////////////////////////////////////////////////////////////////////////////////////////////////////

void CSprite::GetFModuleRect( irr::core::rect<short>& rc, int frame, int fmodule, int posX, int posY, int flags ) const
{
	ASSERT( 0 <= frame && frame < m_nFrames );

	int off      = m_pFrames_FM_Start[ frame ] + fmodule;
	int fm_flags = m_pFModules_Flags[ off ];
	int index    = m_pFModules_Module[ off ];

	{
		if ( flags & FLAG_FLIP_X )	posX -= m_pFModules_OffsetX[ off ];
		else						posX += m_pFModules_OffsetX[ off ];
		if ( flags & FLAG_FLIP_Y )	posY -= m_pFModules_OffsetY[ off ];
		else						posY += m_pFModules_OffsetY[ off ];
	}

	if ( ( fm_flags & FLAG_HYPER_FM ) != 0 )
	{
		GetFrameRect( rc, index, posX, posY, fm_flags, 0, 0 );
	}
	else
	{
		ASSERT(0 <= index && index < m_nModules && "Invalid sprite !!!");

		if( ( flags & FLAG_FLIP_X ) != 0 )	posX -= GetModuleWidth( index );
		if( ( flags & FLAG_FLIP_Y ) != 0 )	posY -= GetModuleHeight( index );

		rc.UpperLeftCorner = position2d<short>(posX, posY);
		rc.LowerRightCorner = rc.UpperLeftCorner + position2d<short>(GetModuleWidth( index ), GetModuleHeight( index ));
		//rc->SetWH( posX, posY, GetModuleWidth( index ), GetModuleHeight( index ) );
	}
}

//////////////////////////////////////////////////////////////////////////////////////////////////////

int CSprite::GetFrameWidth(int frame)
{
	rect<short> rc;
	GetFrameRect(rc, frame, 0, 0, 0, 0, 0);
	return rc.getWidth();
}

//////////////////////////////////////////////////////////////////////////////////////////////////////

int CSprite::GetFrameHeight(int frame)
{
	rect<short> rc;
	GetFrameRect(rc, frame, 0, 0, 0, 0, 0);
	return rc.getHeight();
}

//////////////////////////////////////////////////////////////////////////////////////////////////////
//
//void CSprite::GetModuleRect( CRect* rc, int module, int posX, int posY, u32 flags) const
//{
//	ASSERT( 0 <= module && module < m_nModules );
//
//	rc->SetWH( posX, posY, GetModuleWidth( module ), GetModuleHeight( module ) );
//}
//////////////////////////////////////////////////////////////////////////////////////////////////////
//
//void CSprite::GetFrameRects ( CRect* rc, int frame , int flag , int type  )
//{
//	
//}
//
//////////////////////////////////////////////////////////////////////////////////////////////////////
//
//void CSprite::GetFrameTriangle ( CTriangle* tri, int frame , int flag , int type  )
//{
//	ASSERT( 0 <= frame && frame < m_nFrames );
//	
//	int x = 0, y = 0, x1 = 0, y1 = 0, x2 = 0, y2 = 0 ;
//
//	if (m_nFlags & BST_FLAG_MODULE_TYPE)
//	{
//		int crtType = -1;
//		int off = m_pFrames_FM_Start[frame];
//		for (int i=0; i < m_pFrames_NoFModules[frame]; i++)
//		{
//			int index = m_pFModules_Module[ off + i ];
//
//			if (m_pModules_Type[index] == MODULE_TYPE_TRIANGLE)
//			{
//				crtType++;
//			}
//
//			if (crtType == type)
//			{
//				x = m_pFModules_OffsetX[ off + i ];
//				y = m_pFModules_OffsetY[ off + i ];
//				x1 = x + (int)m_pModules_U1[ index ];
//				y1 = y + (int)m_pModules_V1[ index ];
//				x2 = x + m_pModules_Width[ index ];
//				y2 = y + m_pModules_Height[ index ];
//				break;
//			}
//		}
//
//		if ((flag & FLAG_FLIP_X) != 0)
//		{
//			x = -x;
//			x1 = -x1;
//			x2 = -x2;
//		}
//	}
//
//	tri->Set(x, y, x1, y1, x2, y2);
//}

////////////////////////////////////////////////////////////////////////////////////////////////////

void CSprite::SetPalette( int nPal )
{
	//for (int i=0; i < m_nbImages; i++)
	//{
	//	if(nPal >= m_pTexture[i]->GetNumPltes())
	//	{
	//		m_nCrtPalette = 0;
	//		return;
	//	}

	//	ASSERT(m_pTexture[i]);
	//	ASSERT(nPal >= 0 && nPal < m_pTexture[i]->GetNumPltes());
	//}

	m_nCrtPalette	=	nPal;
}
////////////////////////////////////////////////////////////////////////////////////////////////////

int CSprite::GetPalette()
{
	return m_nCrtPalette;
}

//////////////////////////////////////////////////////////////////////////////////////////////////////

int CSprite::GetAnimDuration( int anim )
{
	ASSERT( 0 <= anim && anim < m_nAnims );

	int off		=	m_pAnims_AF_Start[ anim ];
	int time	=	0;

	for( int aframe = 0; aframe < GetAFrames( anim ); aframe++, off++ )
	{
		time += m_pAFrames_Time[ off ];
	}

	return time;
}

//////////////////////////////////////////////////////////////////////////////////////////////////////

void CSprite::SetAngle(const irr::core::quaternion& angle)
{
	vector3df euler;
	angle.toEuler(euler);
	m_fAngle = euler.Z;
}

//////////////////////////////////////////////////////////////////////////////////////////////////////

//void CSprite::MultiplyAnimTime(int factor)
//{
//	for(int i = 0 ; i < m_nAFrames; i++)
//	{
//		m_pAFrames_Time[i] *= factor;
//	}
//}

//////////////////////////////////////////////////////////////////////////////////////////////////////
//u8* CSprite::GetTexture(int nTexture)
//{
//	//if (m_pTexture[nTexture]) 
//	//	return m_pTexture[nTexture]->GetTexBuffer(); 
//	
//	return NULL;
//}
//////////////////////////////////////////////////////////////////////////////////////////////////////
//u32 CSprite::GetTextureSize(int nTexture)
//{
//	//if (m_pTexture[nTexture]) 
//	//{
//	//	if(m_nFlags & BST_TYPE_INDEXED)
//	//	{
//	//		return m_pTexture[nTexture]->SizeX() * m_pTexture[nTexture]->SizeY();
//	//	}
//	//	else if(m_nFlags & BST_TYPE_RGB16)
//	//	{
//	//		return m_pTexture[nTexture]->SizeX() * m_pTexture[nTexture]->SizeY() * 2 ; 
//	//	}
//	//	else
//	//	{
//	//		ASSERT(0);
//	//		return 0;
//	//	}		
//	//}
//
//	return 0;
//}
//////////////////////////////////////////////////////////////////////////////////////////////////////
//u32 CSprite::GetTextureWidth(int nTexture)
//{
//	//if (m_pTexture[nTexture]) 
//	//{
//	//	if(m_nFlags & BST_TYPE_INDEXED)
//	//	{
//	//		return m_pTexture[nTexture]->SizeX();
//	//	}
//	//	else if(m_nFlags & BST_TYPE_RGB16)
//	//	{
//	//		return m_pTexture[nTexture]->SizeX() ; 
//	//	}
//	//	else
//	//	{
//	//		ASSERT(0);
//	//		return 0;
//	//	}		
//	//}
//
//	return 0;
//}

//////////////////////////////////////////////////////////////////////////////////////////////////////

//u32 CSprite::GetTextureHeight(int nTexture)
//{
//	//if (m_pTexture[nTexture]) 
//	//{
//	//	if(m_nFlags & BST_TYPE_INDEXED)
//	//	{
//	//		return m_pTexture[nTexture]->SizeY();
//	//	}
//	//	else if(m_nFlags & BST_TYPE_RGB16)
//	//	{
//	//		return m_pTexture[nTexture]->SizeY(); 
//	//	}
//	//	else
//	//	{
//	//		ASSERT(0);
//	//		return 0;
//	//	}		
//	//}
//
//	return 0;
//}

//////////////////////////////////////////////////////////////////////////////////////////////////////

//void CSprite::SetLinearFilter()	
//{
//	//for (int i=0; i < m_nbImages; i++)
//	//{
//	//	m_pTexture[i]->SetFiltering(GL_LINEAR, GL_LINEAR);
//	//}
//}

//////////////////////////////////////////////////////////////////////////////////////////////////////

//void CSprite::SetNearFilter()
//{
//	//for (int i=0; i < m_nbImages; i++)
//	//{
//	//	m_pTexture[i]->SetFiltering(GL_NEAREST, GL_NEAREST);
//	//}
//}
//////////////////////////////////////////////////////////////////////////////////////////////////////
//
//u32 CSprite::GetTextureID(int nTexture , int nPal)
//{ 
//	 //return m_pTexture[nTexture]->GetGLID(nPal); 
//}
//////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////

void CSprite::FillRect(int x, int y, int w, int h, int argb)
{
	rect<s32> r (x, y, x + w, y + h);
	SColor color(argb);
	
	g->device->getVideoDriver()->draw2DRectangle(
				r, color, color, color, color, s_clipRect );
}

void CSprite::FillRect(const rect<int>& rt, int argb)
{
	SColor color(argb);
	
	g->device->getVideoDriver()->draw2DRectangle(
				rt, color, color, color, color, s_clipRect );
}


float CSprite::GetEnlargeRate( irr::c8 *pBaseStr, irr::c8 *pOutStr)
{
	//if( !Application::instance()->IsLoadHighQuality() )
	//{
	//	irr::c8 tmp[256];
	//	sprintf( tmp,"%s.tga", pBaseStr );
	//	strcpy( pOutStr, tmp );
	//	return 1.0f;
	//}

	irr::IrrlichtDevice *pDevice = g->device;
	irr::io::IFileSystem *pFileSystem = pDevice->getFileSystem();

	int enlargeRate = 10;
	bool bFound = false;
	while( enlargeRate>1 && !bFound )
	{
		irr::c8 tmp[256];
		sprintf( tmp,"%s_%d.tga", pBaseStr,enlargeRate );
		
		if( pFileSystem->existFile( tmp ) )
		{
			strcpy( pOutStr, tmp );
			return enlargeRate;
		}
		enlargeRate--;
	}

	irr::c8 tmp[256];
	sprintf( tmp,"%s.tga", pBaseStr );
	strcpy( pOutStr, tmp );
	return 1.0f;
}